package simpleGeom;

public class MSegmentDouble {

		public int id;
		   double x1;
		   double y1;
		    double z1;
		    double x2;
		   double y2;
		   double z2;
		  double vx;
		  double vy;
		  double vz;
		  double c2;
		  
		  public double cX(){
			  return (x1+x2)*0.5f;
		  }
		  public double cY(){
			  return (y1+y2)*0.5f;
		  }
		  public double cZ(){
			  return (z1+z2)*0.5f;
		  }
		  public double dX(){
			  return x2-x1;
		  }
		  public double dY(){
			  return y2-y1;
		  }
		  public double dZ(){
			  return z2-z1;
		  }
		  public double lengthSqr(){
			  return dX()*dX()+dY()*dY()+dZ()*dZ();
		  }
		  public double length(){
			  return (double)Math.sqrt(lengthSqr());
		  }
		  public void scale(double sX,double sY,double sZ){
			  x1*=sX;
			  x2*=sX;
			  y1*=sY;
			  y2*=sY;
			  z1*=sZ;
			  z2*=sZ;
			  reset();
		  }
		  public void translate(double tX,double tY,double tZ){
			  x1+=tX;
			  x2+=tX;
			  y1+=tY;
			  y2+=tY;
			  z1+=tZ;
			  z2+=tZ;
			  reset();
		  }
		  public MSegmentDouble(double x1,double y1,double z1,double x2,double y2,double z2) {
		   this.x1=x1;
		   this.y1=y1;
		   this.z1=z1;
		   this.x2=x2;
		   this.y2=y2;
		   this.z2=z2;
		   reset();
		  }
		  public void reset(){
			  vx=x2-x1;
			   vy=y2-y1;
			   vz=z2-z1;
			   c2=getDot(vx,vy,vz,vx,vy,vz);
		  }


		  public double getDot(double x1,double y1,double z1,double x2,double y2,double z2){
		    return x1*x2+y1*y2+z1*z2;
		  }
		  


		  public double distSqr(double x1,double y1,double z1,double x2,double y2,double z2){
		    double dX=x2-x1;
		    double dY=y2-y1;
		    double dZ=z2-z1;
		    return dX*dX+dY*dY+dZ*dZ;
		  }
		  
		  public double dist(double x1,double y1,double z1,double x2,double y2,double z2){
		    return (double)Math.sqrt(distSqr(x1,y1,z1,x2,y2,z2));
		  }
		  
		  public double[] getClosestPtToSegment(double x, double y, double z){
			 
			  double dx=x-x1;
			    double dy=y-y1;
			    double dz=z-z1;
			    double c1 = getDot(dx,dy,dz,vx,vy,vz);
			    if (c1 <= 0)
			      return new double[]{x1,y1,z1};
			    if (c2 <= c1)
			      return new double[]{x2,y2,z2};
			    double b = c1 / c2;
			    double px=x1+b*vx;
			    double py=y1+b*vy;
			    double pz=z1+b*vz;
			    return new double[]{px,py,pz};
			   
		  }
		  // ===================================================================


		  // dist_Point_to_Segment(): get the distance of a point to a segment
		  // Input: a Point P and a Segment S (in any dimension)
		  // Return: the shortest distance from P to S
		  public double distToSegSqr(double x, double y, double z) {
		    double dx=x-x1;
		    double dy=y-y1;
		    double dz=z-z1;
		    double c1 = getDot(dx,dy,dz,vx,vy,vz);
		    if (c1 <= 0)
		      return distSqr(x,y,z,x1,y1,z1);
		    if (c2 <= c1)
		      return distSqr(x,y,z, x2,y2,z2);
		    double b = c1 / c2;
		    double px=x1+b*vx;
		    double py=y1+b*vy;
		    double pz=z1+b*vz;
		    return distSqr(x,y,z,px,py,pz);
		  }
		  public  double distToSeg(double x, double y, double z) {
		     return (double)Math.sqrt(distToSegSqr(x,y,z));
		   }
		  public double distToLineSqr(double x,double y,double z){
		    double dx=x-x1;
		    double dy=y-y1;
		    double dz=z-z1;
		    double c1 = getDot(dx,dy,dz,vx,vy,vz);
		    double b = c1 / c2;
		    double px=x1+b*vx;
		    double py=y1+b*vy;
		    double pz=z1+b*vz;
		    return distSqr(x,y,z,px,py,pz);
		  }
		  public double distToLine(double x,double y,double z){
		    return (double)Math.sqrt(distToLineSqr(x,y,z));
		  }
		public double x1() {
			return x1;
		}
		public void setX1(double x1) {
			this.x1 = x1;
			reset();
		}
		public double y1() {
			return y1;
		}
		public void setY1(double y1) {
			this.y1 = y1;
			reset();
		}
		public double z1() {
			return z1;
		}
		public void setZ1(double z1) {
			this.z1 = z1;
			reset();
		}
		public double x2() {
			return x2;
		}
		public void setX2(double x2) {
			this.x2 = x2;
			reset();
		}
		public double y2() {
			return y2;
		}
		public void setY2(double y2) {
			this.y2 = y2;
			reset();
		}
		public double z2() {
			return z2;
		}
		public void setZ2(double z2) {
			this.z2 = z2;
			reset();
		}
		



}
